package cn.alise.util;

import java.security.Security;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class AesUtil {
	
	/** 
     * 密钥算法 
     */  
    private static final String ALGORITHM = "AES";  
    /** 
     * 加解密算法/工作模式/填充方式 
     */  
    private static final String ALGORITHM_MODE_PADDING = "AES/ECB/PKCS7Padding";

    public static void main(String[] args) throws Exception {
		
//		AesUtil aesTool = new AesUtil();
//		String key = "62ab9a18288d447f83ce93140d1628c5".toUpperCase().substring(8, 24);
//		System.out.println("key:" + key);
//		Map<String, String> contentMap = new HashMap<String, String>();
//		contentMap.put("cId", "11111111");
//		contentMap.put("cName", "张三");
//		String xml = JsonUtil.toJSON(contentMap);
//		System.out.println(xml);
//		String encrypted = aesTool.encrypt(xml, key);
//		System.out.println("encrypted: \n" + encrypted);
//		System.out.println("encrypted length: \n" + encrypted.length());
//		String decrypted = aesTool.decrypt(encrypted, key);
//		System.out.println("decrypted: \n" + decrypted);
//		System.out.println("decrypted length: \n" + decrypted.length());
//		boolean isSuccessful = false;
//		if (decrypted.equals(xml)) {
//			isSuccessful = true;
//		}
//		System.out.println(isSuccessful);
	}

	/**
	 * cipher instance AES/CBC/NoPadding </br>
	 * padding 0 </br>
	 * unicode UTF-8 </br>
	 * @param content
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static String encrypt(String content, String key) throws Exception {
		
	    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
	    int blockSize = cipher.getBlockSize();
	    byte[] dataBytes = content.getBytes("UTF-8");
	    int plaintextLength = dataBytes.length;
	    if (plaintextLength % blockSize != 0) {
	        plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
	    }
	    
	    byte[] plaintext = new byte[plaintextLength];
	    System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
	   
	    SecretKeySpec keyspec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
	    IvParameterSpec ivspec = new IvParameterSpec(key.getBytes("UTF-8"));
	    cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
	    
	    byte[] encrypted = cipher.doFinal(plaintext);
	    return Base64.encodeBase64String(encrypted).replaceAll("\\s+|\n|\r|\t", "");
	}
	
	/**
	 * cipher instance AES/CBC/NoPadding </br>
	 * padding 0 </br>
	 * unicode UTF-8 </br>
	 * @param content
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static String decrypt(String content, String key) throws Exception {
	
		String ret = null;
		byte[] encrypted = Base64.decodeBase64(content);
	
	    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
	    
	    SecretKeySpec keyspec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
	    IvParameterSpec ivspec = new IvParameterSpec(key.getBytes("UTF-8"));
	
	    cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
	    byte[] original = cipher.doFinal(encrypted);
	    ret = new String(original, "utf-8");
	    return ret.trim();
	}
	
	/** 
     * AES加密 
     *  
     * @param data 加密内容
     * @param password 加密密码
     * @return 
     * @throws Exception 
     */  
    public static String encryptData(String data,String password) throws Exception {  
        //Security.addProvider(new BouncyCastleProvider());  
        // 创建密码器  
        Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING);  
        // 初始化为加密模式的密码
        cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(password));
        // 加密
        byte[] result = cipher.doFinal(data.getBytes());
        
        return  Base64Util.encode(result);
    }  
  
    /** 
     * AES解密 
     *  
     * @param base64Data 解密内容
     * @param password 解密密码
     * @return 
     * @throws Exception 
     */  
    public static String decryptData(String base64Data, String password) throws Exception {  
        Security.addProvider(new BouncyCastleProvider());
        // 创建密码器  
        Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING); 
        //使用密钥初始化，设置为解密模式
        cipher.init(Cipher.DECRYPT_MODE, getSecretKey(password));
        //执行操作
        byte[] result = cipher.doFinal(Base64Util.decode(base64Data));
        
        return new String(result, "utf-8");  
    }
	
	/**
     * 生成加密秘钥
     *
     * @return
     */
    public static SecretKeySpec getSecretKey(String password) {
        SecretKeySpec key = new SecretKeySpec(MD5Util.MD5Encode(password, "UTF-8").toLowerCase().getBytes(), ALGORITHM);
        return key;
    }
}
